#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <vector>
#include <functional>
#include <sys/wait.h>

using namespace std;

function<void()> tasks[] = {
    []{cout << "printf log task" << endl; } ,
    []{cout << "reload conf task" << endl; } ,
    []{cout << "connect mysql task" << endl; } 
};

void work()
{
    while(true)
    {
        int taskCode = 0;
        int n = read(0, &taskCode, sizeof(taskCode));
        if(n == 0)
        {
            cout << "this process out, pid is:" << getpid() << endl;
            break; 
        }
        tasks[taskCode]();
        cout << "i am work:" << getpid() << endl;
        sleep(1);
    }
}

struct processpoolNode
{
    processpoolNode(int wfd, pid_t id, string name)
        : _wfd(wfd), _sub_process_pid(id), _name(name)
    {
    }
    int _wfd;
    pid_t _sub_process_pid;
    string _name;
};

class processpool
{
public:
    typedef processpoolNode Node;
    processpool(int sub_process_nums)
    {
        vector<int> fds;
        for (int i = 0; i < sub_process_nums; i++)
        {
            int fdpipe[2] = {0};
            int pipeRet = pipe(fdpipe);
            if (pipeRet < 0)
                exit(2);
            pid_t id = fork();
            if (id == 0)
            {
                for(auto fd : fds)
                {
                    close(fd);
                }
                close(fdpipe[1]);
                dup2(fdpipe[0], 0);
                work();

                exit(0);
            }
            close(fdpipe[0]);
            string name = "channel-" + to_string(i);
            _Channels.push_back({fdpipe[1], id, name});
            fds.push_back(fdpipe[1]);
        }
    }
    int GetNextProcessFd()
    {
        static int i = 0;
        int ret = i;
        i++;
        i %= _Channels.size();
        return _Channels[ret]._wfd;
    }
    void sendTask(int Task)
    {
        write(GetNextProcessFd(), &Task, sizeof(Task));
    }
    void KillAll()
    {
        for(auto& channel : _Channels)
        {
            close(channel._wfd);
            int rid = waitpid(channel._sub_process_pid, nullptr, 0);
            if(rid == channel._sub_process_pid)
            {
                cout << "wait sub process:" << rid << endl;
            }
        }
    }
    ~processpool()
    {
        KillAll();
    }

private:
    vector<Node> _Channels;
};

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        cout << "argc count is error" << endl;
        return 1;
    }

    int cnt = stoi(argv[1]);
    processpool pool(cnt);

    int n = 3;
    int i = 0;
    while(n--)
    {
        pool.sendTask(i);
        i++;
        i %= 3;
        sleep(1);
    }


    return 0;
}